package com.shuhe.handler;

import com.alibaba.fastjson.JSONObject;
import com.shuhe.domain.api.ApiRequestBody;
import com.shuhe.domain.api.ApiResponseBody;
import com.shuhe.metastore.DBSql;
import com.shuhe.metastore.MetaMysql;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;

import static com.shuhe.common.CommonFunction.*;
import static com.shuhe.handler.ServiceDetail.decryptToken;
import static com.shuhe.handler.ServiceDetail.getTableUpdateName;


public class JsonApiHandler extends HttpServlet {

    private static Logger logger = Logger.getLogger(JsonApiHandler.class);

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        try {


            resp = setResponse(resp);
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("application/json");
            String tokenKey = req.getHeader("token");
            if (tokenKey == null) {
                return;
            }

            String resultStr = "";

            resp.getWriter().write(resultStr);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void makeFailBody(String msg, HttpServletResponse resp, Connection metaConn, String id,
                              String userName) throws Exception {
        ApiResponseBody body = new ApiResponseBody();
        body.setStatus("201");
        body.setMsg(msg);
//        SimpleDateFormat nyr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        String res_time = nyr.format(new Date());
//        String sql = "insert into data_api_log(res_time, res_status, err_detail, id, user_name) values('" + res_time
//                + "','fail','失败：" + msg + "','" + id + "','" + userName + "')";
//        MetaMysql.execSql(metaConn, sql);
        resp.getWriter().write(JSONObject.toJSONString(body));
    }


    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Connection dbConn = null;
        Connection metaConn = null;
        String id = getUUID();
        String userName = "";
        try {
            metaConn = MetaMysql.connect();
            dbConn = DBSql.connect();
            resp.setCharacterEncoding("utf-8");
            resp.setContentType("application/json");
            resp = setResponse(resp);
            String bodyStr = readAsChars(req);
            JSONObject bodyJson = JSONObject.parseObject(bodyStr);
            ApiRequestBody apiReq = JSONObject.toJavaObject(bodyJson, ApiRequestBody.class);
            String columnName = apiReq.getColumnNames();
            String groupColumn = apiReq.getGroupColumn();
            String aggregationColumn = apiReq.getAggregationColumn();
            String rows = apiReq.getRows();
            String offset = apiReq.getOffset();

            String whereCondition = apiReq.getWhereCondition();
            String orderColumn = apiReq.getOrderColumn();
            SimpleDateFormat nyr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String req_time = nyr.format(new Date());
            String tokenKey = req.getHeader("sh_token");
            if (tokenKey == null) {
                tokenKey = "";
            }
            String tableName = req.getParameter("tableName");
            if (tableName == null) {
                tableName = "";
            }
            String serviceCode = req.getHeader("sh_service_code");
            if (serviceCode == null) {
                serviceCode = "";
            }
            if (tableName.length() == 0) {
                makeFailBody("表名为必传参数", resp, metaConn, id, userName);
                return;
            }

            //根据用户token，进行鉴权
            userName = decryptToken(tokenKey);
            String sql = "select b.table_type, b.table_name " +
                    "from service_audit a, standard_table b  " +
                    "\n where a.reg_id = b.id and a.user_name = '" + userName
                    + "' and b.table_name = '" + tableName + "'"
                    + " and a.run_statu = '0'";

            ResultSet rs = MetaMysql.querySql(metaConn, sql);
            ArrayList<String> tableNames = new ArrayList();
            String db_name = "";
            while (rs.next()) {
                db_name = rs.getString("table_type");
                tableNames.add(rs.getString("table_name"));
            }
            Boolean noTable = false;
            if (!tableNames.contains(tableName)) {
                noTable = true;
            }
            if (noTable) {
                makeFailBody("用户没有访问表的权限", resp, metaConn, id, userName);
                return;
            }
            if (columnName.length() <= 0) {
                makeFailBody("列名为必传参数", resp, metaConn, id, userName);
                return;
            }
            if (Integer.parseInt(rows) > 1000) {
                makeFailBody("最大返回行数不能超过1000行", resp, metaConn, id, userName);
                return;
            }

            if (tableName.indexOf(".") >= 0){
                sql = "select count(*) from " + tableName;
            } else{
                sql = "select count(*) from " + db_name + "." + tableName;
            }

            if (whereCondition.length() > 0) {
                sql = sql + " where " + whereCondition;
            }
            if (groupColumn.length() > 0) {
                sql = sql + " group by " + groupColumn;
            }
            int recordNum = 0;
            rs = DBSql.querySql(dbConn, sql);
            if (rs.next()) {
                recordNum = rs.getInt(1);
            }
            if (aggregationColumn.length() > 0) {
                //聚合查询，返回字段为聚合字段
                columnName = aggregationColumn;
            }

            if (tableName.indexOf(".") >= 0){
                sql = "select " + columnName + " from " + tableName;
            } else{
                sql = "select " + columnName + " from " + db_name + "." + tableName;
            }

            if (whereCondition.length() > 0) {
                sql = sql + " where " + whereCondition;
            }
            if (groupColumn.length() > 0) {
                sql = sql + " group by " + groupColumn;
            }
            if (orderColumn.length() > 0) {
                sql = sql + " order by " + orderColumn;
            }

            sql = sql + " limit " + rows + " offset " + offset;
            rs = DBSql.querySql(dbConn, sql);
            ApiResponseBody body = new ApiResponseBody();
            body.setStatus("200");
            body.setMsg("查询成功");
            body.setTotalRowNumber(String.valueOf(recordNum));
            body.setData(getResultSet(rs));
            String res_body = JSONObject.toJSONString(body);
            int resLen = res_body.length();
            if (resLen > 499) {
                resLen = 499;
            }

            //日志
//            sql = "insert into data_api_log(\n" +
//                    "id,user_name,req_time,table_ename,table_columns,order_column,off_set,off_rows, res_time, " +
//                    "res_body, res_status)\n" +
//                    "values('" + id + "','" +
//                    userName + "','" + req_time + "','" + tableName + "','" + columnName + "','" + orderColumn + "','"
//                    + offset + "','" + rows + "','" + nyr.format(new Date()) + "','"
//                    + res_body.substring(0, resLen) + "','" + "success')";
//            MetaMysql.execSql(metaConn, sql);
            resp.getWriter().print(res_body);
        } catch (Exception ex) {
            try {
                int exLen = ex.getMessage().length();
                if (exLen > 499) {
                    exLen = 499;
                }
                makeFailBody(ex.getMessage().substring(0, exLen), resp, metaConn, id, userName);
            } catch (Exception ex1) {

            }
            ex.printStackTrace();
        } finally {
            closeDb(dbConn);
            closeDb(metaConn);
        }
    }


    @Override
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp = setResponse(resp);
    }
}
